var Vue = (function () {
    function Vue(options) {
        var recycles = {
            beforeCreate: options.beforeCreate && options.beforeCreate.bind(this),
            created: options.created && options.created.bind(this),
            beforeMount: options.beforeMount && options.beforeMount.bind(this),
            mounted: options.mounted && options.mounted.bind(this)
        }
        recycles.beforeCreate && recycles.beforeCreate();
        this.$data = options.data();
        this.$el = document.querySelector(options.el);
        this._init(this, options.methods, options.template, recycles);
    }
    Vue.prototype._init = function (vm, methods, template, recycles) {
        recycles.created && recycles.created();
        var container = document.createElement('div');
        container.innerHTML = template;
        var showPool = new Map();
        var eventPool = new Map();
        initData(vm, showPool);
        initPool(container, methods, showPool, eventPool);
        bindEvent(vm, eventPool);
        recycles.beforeMount && recycles.beforeMount()
        render(vm, showPool, container);
        recycles.mounted && recycles.mounted()
    }

    function bindEvent(vm, eventPool) {
        for (var [dom, handler] of eventPool) {
            vm[handler.name] = handler;
            dom.addEventListener('click', vm[handler.name].bind(vm), false)
        }
    }

    function initPool(container, methods, showPool, eventPool) {
        var oAllNodes = container.getElementsByTagName('*'),
            dom = null;
        for (var i = 0; i < oAllNodes.length; i++) {
            dom = oAllNodes[i];
            var oIf = dom.getAttribute('v-if');
            var oShow = dom.getAttribute('v-show');
            var oEvent = dom.getAttribute('@click');
            if (oIf) {
                showPool.set(dom, {
                    type: 'if',
                    prop: oIf
                })
                dom.removeAttribute('v-if');
            } else if (oShow) {
                showPool.set(dom, {
                    type: 'show',
                    prop: oShow
                })
                dom.removeAttribute('v-show');
            }

            if (oEvent) {
                eventPool.set(dom, methods[oEvent])
                dom.removeAttribute('@click');
            }
        }
    }

    function initData(vm, showPool) {
        var data = vm.$data;
        for (var key in data) {
            (function (key) {
                Object.defineProperty(vm, key, {
                    get: function () {
                        return data[key];
                    },
                    set: function (newValue) {
                        data[key] = newValue;
                        update(vm, key, showPool);
                    }
                })
            })(key);
        }
    }

    function update(vm, key, showPool) {
        var _data = vm.$data;
        for (var [dom, info] of showPool) {
            if (info.prop === key) {
                switch (info.type) {
                    case 'if':
                        _data[info.prop] ? info.comment.parentNode.replaceChild(dom, info.comment) : dom.parentNode.replaceChild(info.comment, dom);
                        break;
                    case 'show':
                        _data[info.prop] ? (dom.style.display = "block") : (dom.style.display = "none");
                        break;
                    default:
                        break;
                }
            }
        }
    }


    function render(vm, showPool, container) {
        var _data = vm.$data;
        var _el = vm.$el;
        for (var [dom, info] of showPool) {
            switch (info.type) {
                case 'if':
                    info.comment = document.createComment(['v-if']);
                    !_data[info.prop] && dom.parentNode.replaceChild(info.comment, dom);
                    break;
                case 'show':
                    _data[info.prop] && (dom.style.display = "block");
                    break;
                default:
                    break;
            }
        }
        _el.appendChild(container);
    }

    return Vue;
})()

export default Vue;